package com.wanggy.mystore.controller;

import com.wanggy.mystore.controller.ex.*;
import com.wanggy.mystore.entity.User;
import com.wanggy.mystore.service.IUserService;
import com.wanggy.mystore.utils.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

//表示该类中所有方法的响应结果以json格式进行数据的响应
@RestController
@RequestMapping("/users")
public class UserController extends BaseController {
    @Autowired
    private IUserService userService;

    @Value("${upLoadFilePath}")
    private String parent;

    //    @PostMapping("/reg")
//    public JsonResult<Void> reg(User user) {
//
//        System.out.println(user);
//
//
//        //创建响应结果对象即 JsonResult 对象
//        JsonResult<Void> result = new JsonResult<>();
//
//        try{
//            //调用userservice的reg方法时可能出现异常，所以需要捕获异常
//            userService.reg(user);
//            result.setState(200);
//            result.setMessage("用户注册成功");
//        } catch (UserNameDuplicatedException e) {
//            result.setState(4000);
//            result.setMessage(e.getMessage());
//        }catch (InsertException e){
//            result.setState(5000);
//            result.setMessage(e.getMessage());
//        }
//
//        //返回响应数据
//        return result;
//    }

    //用户注册方法
    @PostMapping("/reg")
    public JsonResult<Void> reg(User user) {
        //创建响应结果对象即 JsonResult 对象
        JsonResult<Void> result = new JsonResult<>();
        userService.reg(user);
        result.setState(OK);
        result.setMessage("用户注册成功");
        return result;
    }

    //用户登录方法
    @PostMapping("/login")
    public JsonResult<User> login(String username, String password, HttpSession session) {

        //调用userservice的login方法时可能出现异常，所以需统一处理异常
        User user = userService.login(username, password);

        //向session对象中完成书的绑定
        session.setAttribute("uid", user.getUid());
        session.setAttribute("username", user.getUsername());

        //测试能否正常获取session中的数据
        //System.out.println(getUidFromSession(session));
        //System.out.println(getUsernameFromSession(session));

        //创建响应结果对象即 JsonResult 对象
        JsonResult<User> result = new JsonResult<>(OK, user);
        result.setMessage("用户登录成功");
        //返回用户登录信息
        return result;
    }


    /**
     * 修改用户密码
     *
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     * @param session     session对象
     * @return 返回密码修改成功或失败的信息
     */
    @PostMapping("/change_password")
    public JsonResult<Void> changePassword(String oldPassword, String newPassword, HttpSession session) {
        //根据session中的uid获取用户的uid 和 username
        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);

        //调用userService的changePassword方法修改用户密码
        userService.changePassword(uid, username, oldPassword, newPassword);

        return new JsonResult<>(OK);
    }


    /**
     * 查询用户数据
     *
     * @param session 获取用户的uid
     * @return 如果不为空则返回数据，如果为空则返回null
     */
    @GetMapping("/get_by_uid")
    public JsonResult<User> get_by_uid(HttpSession session) {
        //通过session获取用户的uid
        Integer uid = getUidFromSession(session);
        User user = userService.getByUid(uid);
        return new JsonResult<>(OK, user);
    }

    /**
     * 修改用户数据
     *
     * @param user    前端传递的用户数据
     * @param session 获取用户的uid
     * @return 返回修改成功或失败的信息
     */
    @PostMapping("/change_info")
    public JsonResult<Void> change_info(User user, HttpSession session) {
        //通过session获取用户的uid
        Integer uid = getUidFromSession(session);

        userService.changeInfo(uid, user);
        return new JsonResult<>(OK);
    }


    @PostMapping("/change_avatar")
    public JsonResult<String> change_avatar(HttpSession session, MultipartFile file) {
        /**
         * 1.参数名称为什么必须用file:在upload.html页面中文件上传组件的name=file，前后端的参数名称需要保持一致
         * 2.参数类型为社么必须是MultipartFile:这个是SpringMVC中封装的一个接口，如果类型是MultipartFile并且参数
         * 名称和前端上传文件的相同，则会自动把整体的数据包传递给file
         */
        //判断文件是否为null
        if (file.isEmpty()) {
            throw new FileEmptyException("文件为空");
        }
        //判断文件大小是否超出限制
        if (file.getSize() > AVATAR_MAX_SIZE) {
            throw new FileSizeException("文件超出限制");
        }
        //判断文件的类型是否在我们规定的后缀类型中
        System.out.println(file.getContentType());
        if (!AVATAR_TYPE.contains(file.getContentType())) {
            throw new FileTypeException("文件类型不支持");
        }

        //上传的文件路径：.../upload/文件名.png
        /**
         * session.getServletContext()获取当前Web应用程序的上下问对象（每次启动tomcat都会创建一个新的上下文对象）
         * getRealPath("/upload")的/代表当前Web应用程序的根目录，通过该相对路径获取绝对路径，返回一个路径字符串
         * 如果不能进行映射返回null,单斜杠可要可不要
         */
        //ServletContext servletContext = session.getServletContext();
        //String parent = servletContext.getRealPath("/upload");//每次启动项目，这个路径变化

        System.out.println(parent); //程序调试使用

        //File对象指向这个路径，通过判断File是否存在得到该路径是否存在
        File dir = new File(parent);
        if (!dir.exists()) {
            //创建当前目录
            dir.mkdirs();
        }

        //获取这个文件名称（文件名+后缀)用UUID
        //工具生成一个新的字符串作为文件名称（好处：避免了因文件名重复发生的覆盖）
        String originalFilename = file.getOriginalFilename();
        System.out.println("originalFilename = " + originalFilename);
        //获取文件拓展名
        assert originalFilename != null;
        int index = originalFilename.lastIndexOf(".");
        String suffix = originalFilename.substring(index);

        //把文件名称转换成UUID格式
        String filename = UUID.randomUUID().toString().toUpperCase() + suffix;
        //在dir目录下创建filename文件（此时是空文件）
        File dest = new File(dir, filename);
        //java可以把一个文件的数据直接吓到同类型的文件中，这里将参数file文件中的数据写道空文件dest中
        try {
            //transferTo是一个封装的方法，用来将file文件中的数据写入到dest文件
            file.transferTo(dest);

            /**
             * 先捕获FileStateException再捕获IOException
             * 是因为后者包含前者，如果先捕获IOException那么FileStateException就永远不能会被捕获
             */
        } catch (FileStateExcetion e) {
            throw new FileStateExcetion("文件状态异常");
        } catch (IOException e) {
            throw new FileUploadIoExcetion("文件读写异常");
        }

        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);
        String avatar = "/upload/" + filename;
        userService.changeAvatar(uid, avatar, username);

        //返回用户头像的路径给前端，将来用于头像显示
        return new JsonResult<String>(OK,avatar);
    }
}
